A latent variable model to make predictions
A forecast task
Let’s take the example of a time series of a given stock market index. We want to predict whether this index will rise or fall in the next time step.
## date measured target
## 1 2004-05-24 -0.2102793333 -1
## 2 2004-05-25 0.5418432556 1
## 3 2004-05-26 -0.0009872216 -1
## 4 2004-05-27 -0.7341004753 -1
## 5 2004-05-28 0.0795940608 1
## 6 2004-05-31 -0.1462255312 -1
Modelization
Consider the nokki dataset above. We want to predict the binary (1/-1) target variable while observing the measured variable. The target variable is considered a hidden Bernoulli-distributed variable while measured is the variable we do observe. We will denote the hidden variable with \(z\) and the observed variable with \(x\).
We construct a Hidden Markov Model (HMM). That model considers a discrete time which will be referred to by the index \(i\in\mathbb{N}\), each line of the dataset corresponding to a discrete time step, so that the index \(i\) as well counts the lines of the dataset, beginning with 1 for the first line.
The binary variables \(z_i\in\{1,\ldots,K\}\) with \(K=2\) are identically distributed \(\forall i\) and together form a discrete-state Markov chain. They are, as already said, hidden.
The variables \(x_i\) are also identically distributed and refer to the observations of the variable measured. They are considered normal distributed and relate to the \(z_i\) by a so called observation model \(p(\underline{x}_i \,|\, z_i)\).
The global relationship between the hidden variables \(z_i\) and the observed variables \(x_i\) is given by the following joint distribution:
\[ \begin{aligned} p(\underline{z}_{1:T} \,, \underline{x}_{1:T}) &= p(\underline{z}_{1:T})\cdot p(\underline{x}_{1:T} \,|\, \underline{z}_{1:T})\\ &= \left[ p(z_1) \cdot \Pi_{t=2}^T p(z_t \,|\, z_{t-1}) \right] \cdot \left[ \Pi_{t=1}^T p(\underline{x}_t \,|\, z_t) \right]\,, \end{aligned} \]
Implementation of the forward algorithm
Given our HMM is fitted, we can make predictions about the hidden variable. How does that work?
We give ourselves a Markov chain with known transition matrix. We describe how to recursively compute the filtered marginals \(p(z_t \,|\, \underline{x}_{1:t})\) in an HMM.
The algorithm has two steps.
The prediction step:
\[ p(z_t=j \,|\, \underline{x}_{1:\,t-1}) = \sum_i p(z_t=j \,|\, z_{t-1}=i) \cdot p( z_{t-1}=i \,|\, \underline{x}_{1:\,t-1}) \] The update step:
\[ \begin{aligned} \alpha_t(j) &:= p(z_t=j \,|\, \underline{x}_{1:\,t}) \\ &= p(z_t=j \,|\, \underline{x}_t, \, \underline{x}_{1:\,t-1}) \\ &= \frac{1}{p(\underline{x}_t \,|\, \underline{x}_{1:\,t-1})} \cdot p(\underline{x}_t \,|\, z_t = j, \, \underline{x}_{1:\,t-1} ) \cdot p(z_t = j \,|\, \underline{x}_{1:\,t-1}) \\ &= \frac{1}{\sum_j p(z_t = j \,|\, \underline{x}_{1:\,t-1}) \cdot p(\underline{x}_t \,|\, z_t = j)} \cdot p(\underline{x}_t \,|\, z_t = j) \cdot p(z_t = j \,|\, \underline{x}_{1:\,t-1}) \end{aligned} \]
At the third line: The relation
\[ p(\underline{x}_t \,|\, z_t = j, \, \underline{x}_{1:\,t-1} ) = p(\underline{x}_t \,|\, z_t = j) \]
is a consequence of the \(d\)-separation property of DAGs: the node \(z_t\) is considered observed insofar as the probability of \(x_t\) is conditional on \(z_t\). Thus the node \(z_t\) separates the DAG in two independent parts.
The denominator of the fraction is seen to be a normalization constant, which we will denote by \(Z_t\).
This process is known as the predict-upgrade cycle. The distribution \(p(z_t=j \,|\, \underline{x}_{1:\,t})\) is called the (filtered) belief state at time t, and is a vector of \(K\) numbers, often denoted by \(\underline{\alpha}_t\).
The proposed algorithm:
How to fit the HMM
Say we have observed the \(x\)-column up to line \(N\) of our dataset, but not the hidden variable, \(z\), then, having observed \(x_{1:N}:=\{x_1,\ldots,x_N\}\), we can determine the parameters of an HMM using maximum likelihood.
The likelihood function is obtained from the joint distribution by marginalizing over the hidden variables \(z_i\):
\[ p(x_{1:N}\,|\,\theta)=\sum_{z_{1:N}} p(x_{1:N},\, z_{1:N}\,|\,\theta) \]
The joint distribution \(p(x_{1:N},\, z_{1:N}\,|\,\theta)\) does not factorize over the summation index.
We see that while considering the following scheme. It shows that if the \(z_i\) where observed, then by \(d\)-separation, the parameter vector for the \(x_i\) and the one for the \(z_i\) would be independent given \(D\), the set of all observed nodes: \(\underline{\theta}_x\perp\underline{\theta}_z\,|\,D\). When the \(z_i\) are not observed, the independence does not hold.
The EM algorithm starts with some initial selection for the model parameters, which we denote by \(\theta^\text{ old}\). In the \(E\) step, we take these parameter values and find the posterior distribution of the hidden variables \(p(z_{1:N}\,|\,x_{1:N},\theta^\text{ old})\). We then use this posterior distribution in order to evaluate the expectation of the logarithm of the complete likelihood function, as a function of the parameters \(\theta\), to give the function \(Q(\theta,\theta^\text{ old})\) defined by:
\[ Q(\theta,\theta^\text{ old}) = \sum_{z_{1:N}} p(z_{1:N}\,|\,x_{1:N},\theta^\text{ old})\cdot p(x_{1:N},\,z_{1:N}\,|\,\theta)\,. \]
Notations
At this point, let us introduce some useful notations. We shall use \(\gamma(z_n)\) to denote the marginal posterior distribution of the hidden variable \(z_n\), and \(\xi(z_{n-1},z_n)\) to denote the joint posterior distribution of two successive hidden variables:
\[ \begin{aligned} \gamma(z_n) &:= p(z_n\,|\,x_{1:N},\theta^\text{ old}) \\ \xi(z_{n-1},z_n) &:= p(z_{n-1},\,z_n\,|\,x_{1:N},\theta^\text{ old})\,. \end{aligned} \]
Because the hidden variables can be represented as \(K\)-dimensional (in our case, \(K=2\)) binary variables using dummy coding, we define \(z_{nk}\) as the \(k\)-th component of such a \(K\)-binary vector. Thus \(z_{nk}\) takes the value 1 if and only if the variable \(z_n\) is equal to its \(k\)-th possible value among \(K\). When we identify the value set of \(z_n\) with \(\{1,\ldots,K\}\), when can write \(p(z_{nk}=1)=p(z_n=k)\) and \(p(z_{nk}=0)=p(z_n\neq k)\).
With that notation, we can write the transition probabilities \(A_{jk}\) defining the transition matrix \(A\) of the Markov chain: \(A_{jk}=p(z_{nk}=1\,|\,z_{n-1,\,j}=1)\). The conditional distributions are then
\[ p(z_n\,|\,z_{n-1},A) = \prod_{k=1}^K \prod_{j=1}^K A_{jk}^{z_{n-1,\,j}\,\cdot\, z_{nk}}\,, \]
the initial parent node being special in that it doesn’t have a parent node:
\[ p(z_i\,|\,\pi) = \prod_{k=1}^K \pi_k^{z_{1k}}\,, \]
where \(\sum_k\pi_k=1\).
With those notations, we can write the joint probability distribution more precisely:
\[ p(x_{1:N},\,z_{1:N}\,|\,\theta) = p(z_1|\underline{\pi})\cdot\left[\prod_{n=2}^N p(z_n\,|\,z_{n-1},A)\right]\cdot \prod_{m=1}^N p(x_m\,|\,z_m,\phi)\, \]
where \(\theta=\{\underline{\pi},A,\phi\}\), \(\phi\) being the parameter of the observation model \(p(x_m\,|\,z_m)\), for example \(\phi=\{\mu,\sigma\}\) for a gaussian observation model, as is the case for us.
The EM algorithm: the E-step
We have obtained above the following expression of the expected \(\log\)-likelihood:
\[ Q(\theta,\theta^\text{ old}) = \sum_{z_{1:N}} p(z_{1:N}\,|\,x_{1:N},\theta^\text{ old})\cdot p(x_{1:N},\,z_{1:N}\,|\,\theta)\,. \]
If we substitute the joint distribution \(p(x_{1:N},\,z_{1:N}\,|\,\theta)\) by the more precise expression obtained just above, and make use of the definitions of \(\gamma\) and \(\xi\), we obtain:
\[ Q(\theta,\theta^\text{ old}) = \sum_{k=1}^K \gamma(z_{ik})\cdot\log(\pi_k) + \sum_{n=2}^N \sum_{j=1}^K \sum_{k=1}^K \xi(z_{n-1,\,j},\,z_{nk})\cdot\log(A_{jk}) + \sum_{n=1}^N \sum_{k=1}^K \gamma(z_{nk})\cdot\log(p(x_n\,|\,\phi_k))\,. \]
The goal of the E-step is to evaluate the quantities \(\gamma(z_n)\) and \(\xi(z_{n-1},\,z_n)\) efficiently. For that purpose, we well use the alpha-beta algorithm, a common variant of the backward-forward algorithm family.
The EM algorithm: the M-step
We have to maximize \(Q(\theta,\theta^\text{ old})\) with respect to the parameters \(\theta=\{\underline{\pi},A,\phi\}\). For doing that we treat \(\gamma(z_n)\) and \(\xi(z_{n-1},\,z_n)\) as constants.
Maximization yields:
\[ \begin{aligned} \pi_k &= \frac{\gamma(z_{1k})}{\sum_{j=1}^K \gamma(z_{ij})}\quad, \\ A_{jk} &= \frac{\sum_{n=2}^N \xi(z_{n-1,\,j},\,z_{nk})}{\sum_{q=1}^K \sum_{n=2}^N \xi(z_{n-1,\,j},\,z_{nq})}\quad. \end{aligned} \]
The EM algorithm must be initialized by choosing starting values for \(\underline{\pi}\) and \(A\) which respect the summation constraints associated with their probabilistic interpretation.
To maximize \(Q(\theta,\theta^\text{ old})\) with respect to \(\phi_k=\{\mu_k,\sigma_k\}\) we can proceed independently, insofar as the \(\phi_k\) are independent for the different components.
Maximization yields:
\[ \begin{aligned} \mu_k &= \frac{\sum_{n=1}^N \gamma(z_{nk})\cdot x_n}{\sum_{n=1}^N \gamma(z_{nk})} \\ \Sigma_k &= \frac{\sum_{n=1}^N \gamma(z_{nk})\cdot(x_n-\mu_k)\cdot(x_n-\mu_k)^T}{\sum_{n=1}^N \gamma(z_{nk})}\quad. \end{aligned} \]
The alpha-beta algorithm
So far, it remains us to compute the \(\gamma\) and \(\xi\) values in order to proceed with the EM algorithm, which in turn will fit our Hidden Markov model (HMM) for the Nokki dataset. With our fitted model, we will then obtain predictions using the online filtering forward algorithm.
We shall omit the dependence on the parameter vector \(\theta^\text{ old}\) because it remains fixed throughout.
Making use of the graph properties specific to the chosen model
By applying the \(d\)-separation on the HMM graph, we get the following conditional independence properties:
- \(p(x_{1:N}\,|\,z_n) = p(x_{1:n}\,|\,z_n)\cdot p(x_{n+1:N}\,|\,z_n)\)
Indeed, every path from anyone of the nodes \(x_1,\ldots,x_{n-1}\) to the node \(x_n\) passed through the node \(z_n\), which is observed.
Similar
explanations yield:
\(p(x_{1:n-1}\,|\,x_n,z_n) = p(x_{1:n-1}\,|\,z_n)\)
\(p(x_{1:n-1}\,|\,z_{n-1},z_n) = p(x_{1:n-1}\,|\,z_{n-1})\)
\(p(x_{1:N}\,|\,z_{n-1},z_n) = p(x_{1:n-1}\,|\,z_{n-1})\cdot p(x_n|z_n)\cdot p(x_{n+1:N}\,|\,z_n)\)
Evaluation of \(\gamma(z_{n})\)
We recall that for a discrete multinomial variable like \(z_n\), which has been dummy recoded as a vector variable \(z_n=(z_{n1},\ldots,z_{nK})^T\), the expected value of one of its components \(z_{nk}\) is just the probability of that component having the value 1: \(E[z_{nk}]=p(z_{nk}=1)\). We thus interested in the posterior distribution \(p(z_n\,|\,x_{1:N})\) of \(z_n\) given the whole observed dataset. This represents a vector of length \(K\) whose entries are the expected values of \(z_{nk}\), \(k=1,\ldots,K\). We thus have:
\[ \gamma(z_n) = p(z_n\,|\,x_{1:N}) = \frac{p(x_{1:N}\,|\,z_n)\cdot p(z_n)}{p(x_{1:N})}. \]
Note that the denominator is implicitely conditioned on \(\theta^\text{ old}\) and hence is the likelihood function of the HMM.
Using the first of the fist of the above given independence properties, we get:
\[ \begin{aligned} \gamma(z_n) &= \frac{p(x_{1:n}\,|\,z_n)\cdot p(x_{n+1:N}\,|\,z_n)}{p(x_{1:N)}} \\ &= \frac{\alpha(z_n)\cdot \beta(z_n)}{p(x_{1:N)}}\quad, \end{aligned} \]
where we define
- \(\alpha(z_n):=p(x_{1:n}\,,z_n)\),
- \(\beta(z_n):=p(x_{n+1:N}\,|\,z_n)\).
\(\alpha(z_n)\) represents the joint probability of observing all of the given data up to time \(n\) as well as the value of \(z_n\), whereas \(\beta(z_n)\) represents the conditional probability of all future data from time \(n+1\) to \(N\) given the value of \(z_n\). Each \(\alpha(z_n)\) and \(\beta(z_n)\) are sets of \(K\) numbers, one for each of the possible settings of the dummy coded binary \(K\)-dimensional vector \(z_n\).
We now come to recursion relations about both \(\alpha(z_n)\) and \(\beta(z_n)\).
\[ \begin{aligned} \alpha(z_n) &= p(x_{1:n}\,,z_n) \\ &= p(x_{1:n}\,|\,z_n)\cdot p(z_n) \\ &= p(x_n|z_n)\cdot p(x_{1:{n-1}}\,|\,z_n)\cdot p(z_n) \\ &= p(x_n|z_n)\cdot p(x_{1:{n-1}}\,,z_n) \\ &= p(x_n|z_n)\cdot \sum_{z_{n-1}}p(x_{1:{n-1}}\,,z_{n-1},z_n) \\ &= p(x_n|z_n)\cdot \sum_{z_{n-1}}p(x_{1:{n-1}}\,,z_n\,|\,z_{n-1})\cdot p(z_{n-1}) \\ &= p(x_n|z_n)\cdot \sum_{z_{n-1}}p(x_{1:{n-1}}\,|\,z_{n-1})\cdot p(z_n\,|\,z_{n-1})\cdot p(z_{n-1}) \\ &= p(x_n|z_n)\cdot \sum_{z_{n-1}}p(x_{1:{n-1}}\,,z_{n-1})\cdot p(z_n\,|\,z_{n-1}) \\ \end{aligned} \]
Thus
\[ \alpha(z_n) = p(x_n|z_n)\cdot \sum_{z_{n-1}}\alpha(z_{n-1})\cdot p(z_n\,|\,z_{n-1})\,. \]
The summation \(\sum_{z_{n-1}}\ldots\) contains \(K\) terms, one for each possible value that the variable \(z_n\) can take. The expression \(\alpha(z_n)\) has to be evaluated for each of the \(K\) possible values that \(z_n\) can take. Thus each step of the \(\alpha\) recurson has computational cost \(\mathcal{O}(K^2)\).
In order to start this recursion, we need an initial condition which is given by
\[ \begin{aligned} \alpha(z_1) &= p(x_1,z_1) \\ &= p(z_1)\cdot p(x_1|z_1) \\ &= \prod_{k=1}^K \big(\pi_k\cdot p(x_1\,|\,\phi_k)\big)^{z_{1k}}\,, \end{aligned} \]
which tells us that \(\alpha(z_{1k})\) must be set equal to \(\pi_k\cdot p(x_i\,|\,\phi_k)\). Starting at the first node of the chain, we can evaluate \(\alpha(z_n)\) for every hidden node \(z_n\).
Initialization
Our hidden variable \(z\) is the Nokki variable target, which has only two possible values, therefore \(K=2\). Our model has parameters \(\theta=\{\underline{\pi},A,\phi\}\) that we initialize arbitrarily with \(\pi=(0.5,0.5)^T\) (observing the sum-to-one constraint), \(A=\begin{bmatrix}1 & 0 \\0.5 & 0.5\end{bmatrix}\) (observing the sum-to-one constraint for each row), and \(\phi=\{\mu=(0,0)^T, \sigma=(1,1)^T\}\), where \(\mu_k\) is the \(k\) component of the vector \(\mu\), and analogous with the vector \(\sigma\).
The parameters \(\underline{\pi}\) and \(A\) define the hidden Markov chain itself, whereas \(\phi\) defines the observation model, which is gaussian.
# Initialization
<- 8 # For the sake of simplicity, we consider only the first nodes of the Markov chain.
N <-2
K<- c(0.5,0.5)
pii <- matrix(c(1, 0, 0.5, 0.5), nrow = 2, ncol = 2)
A <- c(0,0)
mu <- c(1,1)
sigma # The first observed variable, x_1:
$measured[1] nokki
## [1] -0.2102793
The alpha recursion
For the node \(n\), the quantity \(\alpha(z_n)\) will be represented by a \(K\)-dimensional vector, and the whole \(\alpha\) recursion over the nodes will produce a \((N,K)\)-dimensional dataset, the \(n\)-th line associated with the \(n\)-th hidden node \(z_n\) of the Markov chain.
# Initialization of the alpha recursion. The first step
<- data.frame(matrix(0, nrow = N, ncol = K))
alpha colnames(alpha) <- c("k=1", "k=2")
1,1] <- pii[1]*dnorm(nokki$measured[1], mu[1], sigma[1])
alpha[1,2] <- pii[2]*dnorm(nokki$measured[1], mu[2], sigma[2]) alpha[
For subsequent steps from the 2nd, we implement
\[ \alpha(z_n) = p(x_n|z_n)\cdot \sum_{z_{n-1}}\alpha(z_{n-1})\cdot p(z_n\,|\,z_{n-1})\,. \]
where
\[ \begin{aligned} p(x_n|z_n) &= p(x_n|z_n,\phi) \\ &= \prod_{k=1}^K p(x_n|\phi_k)^{z_{nk}} \\ &= \prod_{k=1}^K \mathcal{N}(x_n|\mu_k,\sigma_k)^{z_{nk}} \\ \end{aligned} \]
# From the 2nd step to all next steps
for(n in 2:N){
for(k in 1:K){
<- 1:K
j <- dnorm(nokki$measured[n],mu[k],sigma[k]) * sum(alpha[n-1,j]*A[j,k])
alpha[n,k]
}
} alpha
## k=1 k=2
## 1 0.1951094857 0.1951094857
## 2 0.0672102171 0.0672102171
## 3 0.0268129842 0.0268129842
## 4 0.0081702211 0.0081702211
## 5 0.0032491383 0.0032491383
## 6 0.0012824347 0.0012824347
## 7 0.0004583327 0.0004583327
## 8 0.0001778953 0.0001778953
Similarly, there exists a recursion for the \(\beta(z_n)\). By making use of the conditional independence properties, we get:
\[ \begin{aligned} \beta(z_n) &= p(x_{n+1:N}\,|\,z_n) \\ &= \sum_{z_{n+1}} p(x_{n+1:N}\,,z_{n+1}\,|\,z_n) \\ &= \sum_{z_{n+1}} p(x_{n+1:N}\,|\,z_n,z_{n+1})\cdot p(z_{n+1}|z_n) \\ &= \sum_{z_{n+1}} p(x_{n+1:N}\,|\,z_{n+1})\cdot p(z_{n+1},z_n) \\ &= \sum_{z_{n+1}} p(x_{n+2:N}\,|\,z_{n+1})\cdot p(x_{n+1}|z_{n+1})\cdot p(z_{n+1}|z_n)\,. \\ \end{aligned} \]
Thus
\[ \beta(z_n)=\sum_{z_{n+1}} \beta(z_{n+1})\cdot p(x_{n+1}|z_{n+1})\cdot p(z_{n+1}|z_n)\,. \]
Again we need a starting condition for the recursion, namely a value for \(\beta(z_N)\). To find it, we consider the relationship
\[ \gamma(z_n) = \frac{\alpha(z_n)\cdot \beta(z_n)}{p(x_{1:N)}} \]
by setting \(n=N\). It yields
\[ \gamma(z_N) = \frac{\alpha(z_N)}{p(x_{1:N)}}\cdot \beta(z_N) = \gamma(z_N)\cdot \beta(z_N)\,, \]
a relation that holds only for \(\beta(z_N) = 1\).
The first step of the beta backward recursion
# Initialization of the beta recursion. The first step
<- data.frame(matrix(0, nrow = N, ncol = K))
beta colnames(beta) <- c("k=1", "k=2")
1] <- 1
beta[N,2] <- 1 beta[N,
The beta recursion
# From the 2nd step to all next steps
for(n in 1:(N-1)){
for(k in 1:K){
<- 1:K
j -n,k] <- sum(beta[N-n+1,k] * dnorm(nokki$measured[N-n+1], mu[j], sigma[j]) * A[j,k])
beta[N
}
} beta
## k=1 k=2
## 1 0.0009117715 0.0009117715
## 2 0.0026468486 0.0026468486
## 3 0.0066346687 0.0066346687
## 4 0.0217736172 0.0217736172
## 5 0.0547515214 0.0547515214
## 6 0.1387168275 0.1387168275
## 7 0.3881356717 0.3881356717
## 8 1.0000000000 1.0000000000
Evaluation of the likelihood \(p(x_{1:N})\) as well as \(\gamma(z_n)\) and \(\xi(z_{n-1},z_n)\)
As mentioned, \(p(x_{1:N})\) is implicitly conditioned on \(\theta^\text{ old}\) and is thus really a likelihood, that of our HMM. We implement the below explained formula for the likelihood:
\[ p(x_{1:N})=\sum_{z_N}\alpha(z_N)\,. \]
# Evaluation of the likelihood
<- 1:K
j <- sum(alpha[N,j]) likelihood
For the evaluation of \(\gamma\), we define a \((N,K)\)-dimensional dataset and implement the formula:
\[ \gamma(z_n) = \frac{\alpha(z_n)\cdot \beta(z_n)}{p(x_{1:N)}} \]
# Evaluation of gamma
<- data.frame(matrix(0, nrow = N, ncol = K))
gamma colnames(gamma) <- c("k=1", "k=2")
<- 1:N
n <- 1:K
k <- alpha[n,k]*beta[n,k]/likelihood
gamma[n,k] gamma
## k=1 k=2
## 1 0.5 0.5
## 2 0.5 0.5
## 3 0.5 0.5
## 4 0.5 0.5
## 5 0.5 0.5
## 6 0.5 0.5
## 7 0.5 0.5
## 8 0.5 0.5
Note
In the M-step, the quantity \(p(x_{1:N})\) will cancel out in the equation for \(\mu_k\):
\[ \begin{aligned} \mu_k &= \frac{\sum_{n=1}^N \gamma(z_{nk})\cdot x_n}{\sum_{n=1}^N \gamma(z_{nk})} \\ &=\frac{\sum_{n=1}^N \alpha(z_{nk})\cdot \beta(z_{nk})\cdot x_n}{\sum_{n=1}^N \alpha(z_{nk})\cdot \beta(z_{nk})}\quad. \end{aligned} \]
# Calculation of K-dimensional vector mu
<- 1
k <- 1:N
n for(k in 1:K){
<- sum(alpha[n,k]*beta[n,k]*nokki$measured[n])
numerator <- sum(alpha[n,k]*beta[n,k])
denominator <- numerator/denominator
mu[k]
} mu
## [1] -0.08810001 -0.08810001
However as mentioned above, \(p(x_{1:N})\) represents the likelihood function whose value we need in order to stop the EM algorithm, that knowingly stops when change of the likelihood from step to step becomes less than a given threshold. That’s why we need to evaluate the likelihood :
\[ p(x_{1:N})=\sum_{z_n}\alpha(z_n)\cdot\beta(z_n)=\sum_{z_N}\alpha(z_N)\,. \]
Evaluation of \(\xi(z_{n-1},\,z_{n})\)
\[ \begin{aligned} \xi(z_{n-1},z_n) &= p(z_{n-1},z_n\,|\,x_{1:N}) \\ &= \frac{1}{p(x_{1:N})}\cdot p(x_{1:n-1}\,|\,z_{n-1})\cdot p(x_n|z_n)\cdot p(x_{n+1:N}\,|\,z_n)\cdot p(z_n|z_{n-1})\cdot p(z_{n-1}) \\ &= \frac{1}{p(x_{1:N})}\cdot \Big[\alpha(z_{n-1})\cdot p(x_n|z_n)\cdot p(z_n|z_{n-1}))\cdot \beta(z_n)\Big] \end{aligned} \]
Thus we can calculate the \(\xi(z_{n-1},\,z_{n})\) directly by using the results of \(\alpha\) and \(\beta\) recursions.
For the evaluation of \(\xi\),
# Evaluation of xi
## Definition of the shape of the dataset
<- data.frame(matrix(0, nrow = K*K*N, ncol = 4))
xi colnames(xi) <- c("n","z_{n-1}", "z_n","xi")
for(n in 1:N){
for(j in 1:K){
for(k in 1:K){
*K*(n-1)+K*(j-1)+k,1] <- n
xi[K*K*(n-1)+K*(j-1)+k,2] <- j
xi[K*K*(n-1)+K*(j-1)+k,3] <- k
xi[K
}
}
}## Filling with values for the variable xi
for(n in 1:N){
for(j in 1:K){
for(k in 1:K){
*K*(n-1)+K*(j-1)+k,4] <- (alpha[n,k]*dnorm(nokki$measured[n],mu[k],sigma[k])
xi[K*A[j,k]*beta[n,k])/likelihood
}
}
} xi
## n z_{n-1} z_n xi
## 1 1 1 1 0.19798785
## 2 1 1 2 0.09899393
## 3 1 2 1 0.00000000
## 4 1 2 2 0.09899393
## 5 2 1 1 0.16357233
## 6 2 1 2 0.08178617
## 7 2 2 1 0.00000000
## 8 2 2 2 0.08178617
## 9 3 1 1 0.19871572
## 10 3 1 2 0.09935786
## 11 3 2 1 0.00000000
## 12 3 2 2 0.09935786
## 13 4 1 1 0.16190525
## 14 4 1 2 0.08095262
## 15 4 2 1 0.00000000
## 16 4 2 2 0.08095262
## 17 5 1 1 0.19668607
## 18 5 1 2 0.09834304
## 19 5 2 1 0.00000000
## 20 5 2 2 0.09834304
## 21 6 1 1 0.19913446
## 22 6 1 2 0.09956723
## 23 6 2 1 0.00000000
## 24 6 2 2 0.09956723
## 25 7 1 1 0.18551322
## 26 7 1 2 0.09275661
## 27 7 2 1 0.00000000
## 28 7 2 2 0.09275661
## 29 8 1 1 0.18936569
## 30 8 1 2 0.09468285
## 31 8 2 1 0.00000000
## 32 8 2 2 0.09468285
Summary of the required steps for fitting our HMM
To fit our HMM using the EM algorithm, we first initialize the parameters \(\theta:=(\underline{\pi},A,\underline{\phi})\) by setting them equal to an arbitrary choice \(\theta^\text{ old}\). The \(\underline{\pi}\) and \(A\) parameters can be initialized uniformly or randomly from a uniform distribution, respecting their non-negativity and sum-to-one constraints.
Initialization of the parameters of our gaussian observation model \(\underline{\phi}=\{\underline{\mu},\underline{\sigma}\}=\{(\mu_1,\ldots,\mu_K)^T,\, (\sigma_1,\ldots,\sigma_K)^T\}\) can be done by applying the \(K\)-means algorithm to the data, and \(\sigma_k\) can be initialized to be the variance of the corresponding cluster.
Then we run both the forward \(\alpha\) recursion and the backward \(\beta\) recursion and use the results to evaluate \(\gamma(z_n)\) and \(\xi(z_{n-1},\,z_{n})\). At this stage, we evaluate the likelihood function as well. This completes the E-step. We use the results to find a revised set of parameters \(\theta^\text{ new}\) using the M-step equations. We then continue to alternate between E- and M-steps until the change in the likelihood function is below some threshold.
The running EM algorithm
Now that we have explained and coded each substep of the EM algorithm for HMM, it remains to put it all together.
# Initialization
<- 8 # For the sake of simplicity, we consider only the first nodes of the Markov chain.
N <- 2
K <- vector("numeric",K)
pii <- c(0.5,0.5)
pii <- matrix(vector("numeric",K), nrow = K, ncol = K)
A <- matrix(c(0.25, 0.35, 0.75, 0.65), nrow = 2, ncol = 2)
A <- vector("numeric",K)
mu <- c(0,0)
mu <- vector("numeric",K)
sigma <- c(1,1)
sigma
for(i in 1:1){ #Inserting the above code into a loop is a trick
#that helps for getting it printed in only one block
cat("pii\n")
print(pii)
cat("Markov transition matrix \n")
print(A)
cat("mu\n")
print(mu)
cat("sigma\n")
print(sigma)
cat("\n")
}
## pii
## [1] 0.5 0.5
## Markov transition matrix
## [,1] [,2]
## [1,] 0.25 0.75
## [2,] 0.35 0.65
## mu
## [1] 0 0
## sigma
## [1] 1 1
library(dplyr)
# tables for monitoring parameter convergence
<- data.frame(t(pii))
store_pii <- data.frame(t(mu))
store_mu <- data.frame(t(sigma))
store_sigma <- data.frame(t(c(A)))
store_A <- data.frame(likelihood)
store_likelihood
<- 1
i <- 20
numberOfLoops while(i < numberOfLoops){
# E-step
## Alpha
### Initialization
<- data.frame(matrix(0, nrow = N, ncol = K))
alpha colnames(alpha) <- c("k=1", "k=2")
1,1] <- pii[1]*dnorm(nokki$measured[1], mu[1], sigma[1])
alpha[1,2] <- pii[2]*dnorm(nokki$measured[1], mu[2], sigma[2])
alpha[### Forward recursion
for(n in 2:N){
for(k in 1:K){
<- 1:K
j <- dnorm(nokki$measured[n],mu[k],sigma[k]) * sum(alpha[n-1,j]*A[j,k])
alpha[n,k]
}
}## Beta
### Initialization
<- data.frame(matrix(0, nrow = N, ncol = K))
beta colnames(beta) <- c("k=1", "k=2")
1] <- 1
beta[N,2] <- 1
beta[N,### Backward recursion
for(n in 1:(N-1)){
for(k in 1:K){
<- 1:K
j -n,k] <- sum(beta[N-n+1,k] * dnorm(nokki$measured[N-n+1], mu[j], sigma[j]) * A[j,k])
beta[N
}
}## Likelihood
<- 1:K
j <- sum(alpha[N,j])
likelihood ## Gamma
<- data.frame(matrix(0, nrow = N, ncol = K))
gamma colnames(gamma) <- c("k=1", "k=2")
<- 1:N
n <- 1:K
k <- alpha[n,k]*beta[n,k]/likelihood
gamma[n,k] ## Xi
### Definition of the shape of xi
<- data.frame(matrix(0, nrow = K*K*N, ncol = 4))
xi colnames(xi) <- c("n_value","z_n_moinsUn", "z_n","xi")
for(n in 1:N){
for(j in 1:K){
for(k in 1:K){
*K*(n-1)+K*(j-1)+k,1] <- n
xi[K*K*(n-1)+K*(j-1)+k,2] <- j
xi[K*K*(n-1)+K*(j-1)+k,3] <- k
xi[K
}
}
}<- filter(xi,n_value>1)
xi ### Filling dataset xi with xi-values
for(n in 2:N){
for(j in 1:K){
for(k in 1:K){
*K*(n-2)+K*(j-1)+k,4] <- (alpha[n-1,k]*dnorm(nokki$measured[n],mu[k],sigma[k])
xi[K*A[j,k]*beta[n,k])/likelihood
}
}
}
# M-step
## Pii
<- 1:K
kk for(k in 1:K){
<- gamma[1,k]
numerator <- sum(gamma[1,kk])
denominator <- numerator/denominator
pii[k]
}## A
for(k in 1:K){
for(j in 1:K){
<- 0
numerator for(n in 2:N){
<- numerator + filter(xi,n_value==n & z_n_moinsUn==j & z_n==k)[[4]]
numerator
}<- 0
denominator for(jj in 1:K){
for(n in 2:N){
<- denominator + filter(xi,n_value==n & z_n_moinsUn==j & z_n==jj)[[4]]
denominator
}
}<- numerator/denominator
A[k,j]
}
}## Mu
<- 1:N
n for(k in 1:K){
<- sum(alpha[n,k]*beta[n,k]*nokki$measured[n])
numerator <- sum(alpha[n,k]*beta[n,k])
denominator <- numerator/denominator
mu[k]
}## Sigma
for(k in 1:K){
<- 0
numerator for(n in 1:N){
<- numerator +
numerator *(nokki$measured[n]-mu[k])%*%t(nokki$measured[n]-mu[k])
gamma[n,k]
}<- sum(gamma[n,k])
denominator <- numerator/denominator
sigma[k]
}
if(abs((i/numberOfLoops<0.2))||(abs(numberOfLoops-i)/numberOfLoops<0.2)){
cat("\n Step n = ",i,"\n")
cat("===========\n")
cat("pii\n")
print(pii)
cat("Markov transition matrix \n")
print(A)
cat("mu\n")
print(mu)
cat("sigma\n")
print(sigma)
}
<- rbind(store_pii, data.frame(t(pii)))
store_pii <- rbind(store_mu, data.frame(t(mu)))
store_mu <- rbind(store_sigma, data.frame(t(sigma)))
store_sigma <- rbind(store_A, data.frame(t(c(A))))
store_A <- rbind(store_likelihood,data.frame(likelihood))
store_likelihood
<- i+1
i }
##
## Step n = 1
## ===========
## pii
## [1] 0.002648566 0.997351434
## Markov transition matrix
## [,1] [,2]
## [1,] 0.01706358 0.02727781
## [2,] 0.98293642 0.97272219
## mu
## [1] -0.06597361 -0.02371714
## sigma
## [1] 0.2698719 5.0864943
##
## Step n = 2
## ===========
## pii
## [1] 0.02564032 0.97435968
## Markov transition matrix
## [,1] [,2]
## [1,] 0.9694939 0.98089322
## [2,] 0.0305061 0.01910678
## mu
## [1] -0.0225262 -0.1016069
## sigma
## [1] 0.2924687 1.3919037
##
## Step n = 3
## ===========
## pii
## [1] 0.09203595 0.90796405
## Markov transition matrix
## [,1] [,2]
## [1,] 0.3668192 0.4834276
## [2,] 0.6331808 0.5165724
## mu
## [1] -0.0779264 -0.2744360
## sigma
## [1] 1.061383 5.450796
##
## Step n = 17
## ===========
## pii
## [1] 0.2140877 0.7859123
## Markov transition matrix
## [,1] [,2]
## [1,] 0.3830684 0.5007572
## [2,] 0.6169316 0.4992428
## mu
## [1] -0.07025889 -0.10029462
## sigma
## [1] 1.149351 1.089568
##
## Step n = 18
## ===========
## pii
## [1] 0.2111275 0.7888725
## Markov transition matrix
## [,1] [,2]
## [1,] 0.382485 0.5001398
## [2,] 0.617515 0.4998602
## mu
## [1] -0.07006379 -0.10037659
## sigma
## [1] 1.149705 1.089326
##
## Step n = 19
## ===========
## pii
## [1] 0.2081668 0.7918332
## Markov transition matrix
## [,1] [,2]
## [1,] 0.3819412 0.4995641
## [2,] 0.6180588 0.5004359
## mu
## [1] -0.06986963 -0.10046134
## sigma
## [1] 1.150014 1.089107
Consider the convergence of the likelihood after only a few steps:
## likelihood
## 1 3.557905e-04
## 2 3.557905e-04
## 3 4.865013e-08
## 4 6.044383e-04
## 5 8.356111e-07
## 6 1.029319e-04
## 7 8.724705e-05
## 8 1.416213e-04
## 9 1.682182e-04
## 10 1.753885e-04
## 11 1.782563e-04
## 12 1.797233e-04
## 13 1.805805e-04
## 14 1.811489e-04
## 15 1.815742e-04
## 16 1.819260e-04
## 17 1.822392e-04
## 18 1.825318e-04
## 19 1.828134e-04
## 20 1.830895e-04
We finally compute the predictive distribution: the observed data is \(\{x_1,\ldots,x_N\}\) and we wish to predict \(x_{N+1}\), which is important for real-time applications like, in our case, forecasting.
\[ \begin{aligned} p(x_{N+1}\,|\,x_{1:N}) &= \sum_{z_{N+1}} p(x_{N+1},z_{N+1}\,|\,x_{1:N}) \\ &= \sum_{z_{N+1}} p(x_{N+1}\,|\,z_{N+1},\,x_{1:N})\cdot p(z_{N+1}\,|\,x_{1:N}) \\ &= \sum_{z_{N+1}}\left[ p(x_{N+1}\,|\,z_{N+1})\cdot \sum_{z_N} p(z_{N+1},\,z_N\,|\,x_{1:N}) \right] \\ &= \sum_{z_{N+1}} \left[ p(x_{N+1}\,|\,z_{N+1})\cdot \sum_{z_N} p(z_{N+1}\,|\,z_N)\cdot p(z_N\,|\,x_{1:N}) \right] \\ &= \sum_{z_{N+1}} \left[ p(x_{N+1}\,|\,z_{N+1})\cdot \sum_{z_N} p(z_{N+1}\,|\,z_N)\cdot \frac{p(z_N,\,x_{1:N})}{p(x_{1:N})} \right] \\ &= \frac{1}{p(x_{1:N})}\cdot \sum_{z_{N+1}} \left[ p(x_{N+1}\,|\,z_{N+1}) \cdot \sum_{z_N} p(z_{N+1}\,|\,z_N) \cdot \alpha(z_N) \right] \,. \end{aligned} \]
This quantity can be evaluated by first running a forward alpha recursion and then computing the summations over \(z_N\) (\(K\) terms) and \(z_{N+1}\) (\(K\) terms). The predicted \(x_{N+1}\) can then eventually be used to predict the subsequent value \(x_{N+2}\).
We therefore run an alpha recursion using the obtained parameter values for the hidden Markov chain \(\pi\) and \(A\ldots\)
pii
## [1] 0.2081668 0.7918332
A
## [,1] [,2]
## [1,] 0.3819412 0.4995641
## [2,] 0.6180588 0.5004359
\(\ldots\) as well as for the observation model \(\mu\) and \(\sigma\):
mu
## [1] -0.06986963 -0.10046134
sigma
## [1] 1.150014 1.089107
## Alpha
### Initialization
<- data.frame(matrix(0, nrow = N, ncol = K))
alpha colnames(alpha) <- c("k=1", "k=2")
1,1] <- pii[1]*dnorm(nokki$measured[1], mu[1], sigma[1])
alpha[1,2] <- pii[2]*dnorm(nokki$measured[1], mu[2], sigma[2])
alpha[### Forward recursion
for(n in 2:N){
for(k in 1:K){
<- 1:K
j <- dnorm(nokki$measured[n],mu[k],sigma[k]) * sum(alpha[n-1,j]*A[j,k])
alpha[n,k]
} }
So far we have made the alpha recursion.
We now want to use it to compute the predictive expression that we
obtained above. To do that, we proceed in three steps.
At first we
compute the scalar: \[
\frac{1}{p(x_{1:N})}
\]
As explained before, the denominator is the likelihood:
1/likelihood
## [1] 5461.808
Secondly we compute the \(K\)-dimensional vector (the terms are the coefficients of a \((K,K)\) matrix, and the sum is a vector): \[ \sum_{z_N} p(z_{N+1}\,|\,z_N) \cdot \alpha(z_N) \]
=1:K
k<- 0
sum1 for(j in 1:K){
<- sum1 + A[k,j]*alpha[N,j]
sum1
} sum1
## [1] 8.101248e-05 1.023506e-04
Thirdly we compute the scalar: \[ \sum_{z_{N+1}} \left[ p(x_{N+1}\,|\,z_{N+1}) \cdot \sum_{z_N} p(z_{N+1}\,|\,z_N) \cdot \alpha(z_N) \right] \]
<- 0
sum2 for(k in 1:K){
<- 0
sum1 for(j in 1:K){
<- sum1 + A[k,j]*alpha[N,j]
sum1
}<- sum2 + dnorm(nokki$measured[N],mu[k],sigma[k]) * sum1
sum2
} sum2
## [1] 6.28978e-05
Putting it all together, we get the prediction for the next observation \(x_{N+1}\):
<- 0
sum2 for(k in 1:K){
<- 0
sum1 for(j in 1:K){
<- sum1 + A[k,j]*alpha[N,j]
sum1
}<- sum2 + dnorm(nokki$measured[N],mu[k],sigma[k]) * sum1
sum2
}<- sum2/likelihood
prediction prediction
## [1] 0.3435357
Comparing with the dataset value at corresponding line \(N+1\):
$measured[N+1] nokki
## [1] -0.08156015
In order to measure the prediction rate, one has to test the prediction method many times and do statistics.
Testing the predictive method
We run the EM algorithm many times, each time for an increasing number of observations \(N\). Each run consists of the EM algorithm followed by the prediction procedure. Each run associates a prediction to a \(N\) value.
<- function(N){
EM_algo # Initialization
<- 2
K <- vector("numeric",K)
pii <- c(0.5,0.5)
pii <- matrix(vector("numeric",K), nrow = K, ncol = K)
A <- matrix(c(0.25, 0.35, 0.75, 0.65), nrow = 2, ncol = 2)
A <- vector("numeric",K)
mu <- c(0,0)
mu <- vector("numeric",K)
sigma <- c(1,1)
sigma
# EM algorithm is running
library(dplyr)
# tables for monitoring parameter convergence
<- data.frame(t(pii))
store_pii <- data.frame(t(mu))
store_mu <- data.frame(t(sigma))
store_sigma <- data.frame(t(c(A)))
store_A <- data.frame(likelihood)
store_likelihood
<- 1
i <- 20
numberOfLoops while(i < numberOfLoops){
# E-step
## Alpha
### Initialization
<- data.frame(matrix(0, nrow = N, ncol = K))
alpha colnames(alpha) <- c("k=1", "k=2")
1,1] <- pii[1]*dnorm(nokki$measured[1], mu[1], sigma[1])
alpha[1,2] <- pii[2]*dnorm(nokki$measured[1], mu[2], sigma[2])
alpha[### Forward recursion
for(n in 2:N){
for(k in 1:K){
<- 1:K
j <- dnorm(nokki$measured[n],mu[k],sigma[k]) * sum(alpha[n-1,j]*A[j,k])
alpha[n,k]
}
}## Beta
### Initialization
<- data.frame(matrix(0, nrow = N, ncol = K))
beta colnames(beta) <- c("k=1", "k=2")
1] <- 1
beta[N,2] <- 1
beta[N,### Backward recursion
for(n in 1:(N-1)){
for(k in 1:K){
<- 1:K
j -n,k] <- sum(beta[N-n+1,k] * dnorm(nokki$measured[N-n+1], mu[j], sigma[j]) * A[j,k])
beta[N
}
}## Likelihood
<- 1:K
j <- sum(alpha[N,j])
likelihood ## Gamma
<- data.frame(matrix(0, nrow = N, ncol = K))
gamma colnames(gamma) <- c("k=1", "k=2")
<- 1:N
n <- 1:K
k <- alpha[n,k]*beta[n,k]/likelihood
gamma[n,k] ## Xi
### Definition of the shape of xi
<- data.frame(matrix(0, nrow = K*K*N, ncol = 4))
xi colnames(xi) <- c("n_value","z_n_moinsUn", "z_n","xi")
for(n in 1:N){
for(j in 1:K){
for(k in 1:K){
*K*(n-1)+K*(j-1)+k,1] <- n
xi[K*K*(n-1)+K*(j-1)+k,2] <- j
xi[K*K*(n-1)+K*(j-1)+k,3] <- k
xi[K
}
}
}<- filter(xi,n_value>1)
xi ### Filling dataset xi with xi-values
for(n in 2:N){
for(j in 1:K){
for(k in 1:K){
*K*(n-2)+K*(j-1)+k,4] <- (alpha[n-1,k]*dnorm(nokki$measured[n],mu[k],sigma[k])
xi[K*A[j,k]*beta[n,k])/likelihood
}
}
}
# M-step
## Pii
<- 1:K
kk for(k in 1:K){
<- gamma[1,k]
numerator <- sum(gamma[1,kk])
denominator <- numerator/denominator
pii[k]
}## A
for(k in 1:K){
for(j in 1:K){
<- 0
numerator for(n in 2:N){
<- numerator + filter(xi,n_value==n & z_n_moinsUn==j & z_n==k)[[4]]
numerator
}<- 0
denominator for(jj in 1:K){
for(n in 2:N){
<- denominator + filter(xi,n_value==n & z_n_moinsUn==j & z_n==jj)[[4]]
denominator
}
}<- numerator/denominator
A[k,j]
}
}## Mu
<- 1:N
n for(k in 1:K){
<- sum(alpha[n,k]*beta[n,k]*nokki$measured[n])
numerator <- sum(alpha[n,k]*beta[n,k])
denominator <- numerator/denominator
mu[k]
}## Sigma
for(k in 1:K){
<- 0
numerator for(n in 1:N){
<- numerator +
numerator *(nokki$measured[n]-mu[k])%*%t(nokki$measured[n]-mu[k])
gamma[n,k]
}<- sum(gamma[n,k])
denominator <- numerator/denominator
sigma[k]
}
<- rbind(store_pii, data.frame(t(pii)))
store_pii <- rbind(store_mu, data.frame(t(mu)))
store_mu <- rbind(store_sigma, data.frame(t(sigma)))
store_sigma <- rbind(store_A, data.frame(t(c(A))))
store_A <- rbind(store_likelihood,data.frame(likelihood))
store_likelihood
<- i+1
i
}
# Prediction for step N+1
## Alpha
### Initialization
<- data.frame(matrix(0, nrow = N, ncol = K))
alpha colnames(alpha) <- c("k=1", "k=2")
1,1] <- pii[1]*dnorm(nokki$measured[1], mu[1], sigma[1])
alpha[1,2] <- pii[2]*dnorm(nokki$measured[1], mu[2], sigma[2])
alpha[### Forward recursion
for(n in 2:N){
for(k in 1:K){
<- 1:K
j <- dnorm(nokki$measured[n],mu[k],sigma[k]) * sum(alpha[n-1,j]*A[j,k])
alpha[n,k]
}
}## Implementation of the predictive formula for x_{N+1}
<- 0
sum2 for(k in 1:K){
<- 0
sum1 for(j in 1:K){
<- sum1 + A[k,j]*alpha[N,j]
sum1
}<- sum2 + dnorm(nokki$measured[N],mu[k],sigma[k]) * sum1
sum2
}<- sum2/likelihood
prediction return(prediction)
}
EM_algo(8)
## [1] 0.3435357
<- data.frame()
store_predict for(N in 10:16){
<- rbind(store_predict,c(N,EM_algo(N)))
store_predict
}colnames(store_predict) <- c("step N", "prediction for step N+1")
store_predict
## step N prediction for step N+1
## 1 10 0.3325959
## 2 11 0.3243835
## 3 12 0.1947939
## 4 13 0.1897608
## 5 14 0.1920680
## 6 15 0.1882866
## 7 16 0.1753298
History of the involved concepts
The problem of estimating the parameters of a multivariate data set which contains unobserved data can be managed by decomposing the original estimation problem into smaller estimation problems by factoring the likelihood of the data into a product of likelihoods ((Rubin, 1974)). We are here considering incomplete data: let us consider two sample spaces Y and X and a many-to-one mapping X -> Y. The observed data is a realization y of Y. The corresponding x in X is not observed directly, but only through y. An incomplete data in that sense is composed of both x and y, as well as a probability model describing the relationship between x and y. The problem is that the factorization of its likelihood is not always possible. Whether factorization is possible or not depends on the d-separation properties of the directed acyclic graph associated with the joint distribution of the incomplete data.
(Dempster et al., 1977) introduces a new method for computing a maximum likelihood estimates from incomplete data, that can be used when factorization of the incomplete data is not possible. The method consists in computing iteratively the maximum likelihood estimates. Each iteration of the algorithm consists of an expectation step (E-step) followed by a maximization step (M-step), which is why the method is called the EM algorithm.
(Baum and Petrie, 1966) first introduces the basic theory of hidden Markov models (HMM). This article deals with statistical inference related to finite-state Markov chains, leaving aside the question of the fit of a Markov chain for a given data set. Typically the HMM does not allow the factorization of the likelihood of the incomplete data. (Rabiner, 1989) introduces hidden Markov models for speech recognition tasks. The article covers the basics of HMMs, their application to speech recognition as a sequence labeling problem, and the modeling of temporal dynamics and variability of speech. It also addresses the advantages and disadvantages of using HMMs for speech recognition. (GHAHRAMANI, 2011) shows possible extensions of the use of HMMs considering multiple hidden state variables, multiscale representations, and mixed discrete and continuous variables.
The EM algorithm is typically used to fit mixture models. Baum-Welch (Baum et al., 1970) shows that using the forward-backward algorithm the EM algorithm can also be used to fit MMH, thus avoiding the difficulty around factorization of the likelihood. The adapted form of the EM algorithm to fit HMM is called therefore the Baum-Welch algorithm.
Baum, L.E., Petrie, T., 1966. Statistical Inference for Probabilistic Functions of Finite State Markov Chains. The Annals of Mathematical Statistics 37, 1554–1563.
Baum, L.E., Petrie, T., Soules, G., Weiss, N., 1970. A Maximization Technique Occurring in the Statistical Analysis of Probabilistic Functions of Markov Chains. The Annals of Mathematical Statistics 41, 164–171.
Dempster, A.P., Laird, N.M., Rubin, D.B., 1977. Maximum Likelihood from Incomplete Data via the EM Algorithm. Journal of the Royal Statistical Society. Series B (Methodological) 39, 1–38.
GHAHRAMANI, Z., 2011. AN INTRODUCTION TO HIDDEN MARKOV MODELS AND BAYESIAN NETWORKS. International Journal of Pattern Recognition and Artificial Intelligence. https://doi.org/10.1142/S0218001401000836
Rabiner, L.R., 1989. A tutorial on hidden Markov models and selected applications in speech recognition. Proceedings of the IEEE 77, 257–286. https://doi.org/10.1109/5.18626
Rubin, D.B., 1974. Characterizing the Estimation of Parameters in Incomplete-Data Problems. Journal of the American Statistical Association 69, 467–474. https://doi.org/10.2307/2285680